package com.sneakxy.mybatis.commons.repository.query.executor;

import java.lang.reflect.Method;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.MethodUtils;

import com.sneakxy.mybatis.commons.orm.MybatisEntityManager;
import com.sneakxy.mybatis.commons.orm.mapping.MybatisColumn;
import com.sneakxy.mybatis.commons.repository.query.parser.MybatisCommonsParamNameResolver;

/**
 * @author 潜行的青衣
 */
public abstract class AbstractRepositoryExecutor<T> implements RepositoryExecutor<T> {

	private MybatisEntityManager entityManager;
	
	private MybatisCommonsParamNameResolver resolver;
	
	private Method method;
	
	private String statement;
	
	public AbstractRepositoryExecutor(MybatisEntityManager entityManager, Class<?> loader, String method, Class<?>...type) {
		this(entityManager, MethodUtils.getMatchingMethod(loader, method, type));
	}
	
	public AbstractRepositoryExecutor(MybatisEntityManager entityManager, Method method) {
		this.entityManager = entityManager;
		this.method = method;
		this.resolver = new MybatisCommonsParamNameResolver(
				this.getEntityManager().getConfiguration(), this.getMethod());
		this.buildStatement();
	}
	
	public MybatisEntityManager getEntityManager() {
		return entityManager;
	}

	public MybatisCommonsParamNameResolver getResolver() {
		return resolver;
	}

	public Method getMethod() {
		return method;
	}

	private void buildStatement() {
		StringBuilder idBuilder = new StringBuilder();
		idBuilder.append(this.getMethod().getName());
		Class<?>[] types = this.getMethod().getParameterTypes();
		if(types != null) {
			for(Class<?> type:types) {
				idBuilder.append("-").append(type.getSimpleName());
			}
		}
		idBuilder.append("#Repository");
		this.statement = this.getEntityManager().getNamespacedId(idBuilder.toString());
		this.onBuildStatment();
	}
	
	protected abstract void onBuildStatment();
	
	protected String getParameterPath(MybatisColumn column) {
		StringBuilder result = new StringBuilder();
		int firstIndex = StringUtils.indexOf(column.getPropertyPath(), ".");
		int secondIndex = StringUtils.indexOf(column.getPropertyPath(), ".", firstIndex + 1);
		result.append(StringUtils.substring(column.getPropertyPath(), 0, firstIndex));
		if(secondIndex > -1) {
			result.append(StringUtils.substring(column.getPropertyPath(), secondIndex));
		}
		return result.toString();
	}
	
	protected String getStatement() {
		return statement;
	}

	protected void setStatement(String statement) {
		this.statement = statement;
	}

	protected Object createParameterObject(Object[] parameters, boolean isPageCount) {
		return resolver.getNamedParams(parameters, isPageCount);
	}
	
}
